<html>
<head><meta charset="utf-8"><title>Can inline asm read past the end of arrays/allocations/etc? · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html">Can inline asm read past the end of arrays/allocations/etc?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="215530220"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215530220" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215530220">(Nov 04 2020 at 00:56)</a>:</h4>
<p>There are a lot of times when implementing certain string algorithms where <em>cautiously</em>¹ reading past the end of an array/allocated piece of memory is beneficial.</p>
<p>One example is something like <code>strlen</code> — a pure-rust implementation currently must read every byte individually, which is terrible for performance compared to what performant implementations do. Pretty obviously pure Rust code isn't allowed to (unless I've drastically misunderstood things).</p>
<p>I've been tentatively hoping (and more-or-less assuming) that inline asm would allow this in some capacity²</p>
<p>The current text for the new inline asm says:</p>
<blockquote>
<p>The set of memory locations that assembly code is allowed the read and write are the same as those allowed for an FFI function. ... Refer to the unsafe code guidelines for the exact rules.</p>
</blockquote>
<p>It's not exactly clear (to me) which specific bit of the guidelines is being referenced, or if it's more of a "the UCG is expected to hammer this out eventually" situation. (Sorry if I'm just blind and missed it, though).</p>
<p>Concretely, it's hard to imagine this kind of thing <em>not</em> working (in the case that the code is careful to avoid the cases where this would trap, etc).</p>
<p>Especially as you move the slider towards "more work done in inline asm"... Additionally, FFI functions are allowed to pass these pointers to libc, which will absolutely do this... (But maybe they can only do it because they're libc, exercising a similar privilege that Rust stdlib is allowed)....</p>
<p>Anyway, I felt like it warranted some discussion about whether or not it's strictly allowed, since this is very desirable for certain algorithms.</p>
<p>¹ Yes, yes, cautiously enough.</p>
<p>² Even that capacity is "you have to do most of the work inside the inline asm block" it would be acceptable... Ideally this wouldn't be the only option, though...</p>



<a name="215530643"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215530643" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215530643">(Nov 04 2020 at 01:02)</a>:</h4>
<p>(CC <span class="user-mention" data-user-id="143274">@Amanieu</span>, in case you're interested in this discussion / have an opinion here)</p>



<a name="215531098"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531098" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531098">(Nov 04 2020 at 01:10)</a>:</h4>
<p>I've been arguing to have volatile loads do this (allow "invalid" reads) so you wouldn't even need inline asm.</p>



<a name="215531114"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531114" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531114">(Nov 04 2020 at 01:10)</a>:</h4>
<p>In my view a volatile load/store is the same as an inline asm block with a load/store instruction.</p>



<a name="215531118"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531118" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531118">(Nov 04 2020 at 01:11)</a>:</h4>
<p>I'd certainly be happy with that</p>



<a name="215531151"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531151" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531151">(Nov 04 2020 at 01:11)</a>:</h4>
<p>I assume that would produce llvm-style <code>undef</code> though, and e.g. if i read a <code>usize</code> where only one byte is past the end of the allocation, the whole <code>usize</code> is <code>undef</code> (according at least to LLVM)</p>



<a name="215531211"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531211" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531211">(Nov 04 2020 at 01:12)</a>:</h4>
<p>You can't const-propagate through volatile operations, so <code>undef</code> is never returned.</p>



<a name="215531218"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531218" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531218">(Nov 04 2020 at 01:12)</a>:</h4>
<p>ah, okay, interesting.</p>



<a name="215531254"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531254" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531254">(Nov 04 2020 at 01:13)</a>:</h4>
<p>Fundamentally, algorithms which read out of bounds rely on the fact that memory protection only works on a page granularity. So if you don't cross page boundaries then memory accesses won't fault. They still return garbage data though.</p>



<a name="215531302"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531302" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531302">(Nov 04 2020 at 01:14)</a>:</h4>
<p>yeah that's what i meant by "cautiously" above.</p>



<a name="215531305"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531305" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531305">(Nov 04 2020 at 01:14)</a>:</h4>
<p>(garbage only for the bytes that are OOB)</p>



<a name="215531335"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531335" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531335">(Nov 04 2020 at 01:14)</a>:</h4>
<p>Though keep in mind that <span class="user-mention" data-user-id="120791">@RalfJ</span> and I have disagreements on the semantics of volatile.</p>



<a name="215531390"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531390" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531390">(Nov 04 2020 at 01:15)</a>:</h4>
<p>it goes against <a href="https://www.ralfj.de/blog/2019/07/14/uninit.html">https://www.ralfj.de/blog/2019/07/14/uninit.html</a> IIUC, although perhaps that could be adjusted for volatile if that's really not an issue.</p>



<a name="215531554"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531554" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Diggsey <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531554">(Nov 04 2020 at 01:18)</a>:</h4>
<p>My expection is that all volatile operations are considered I/O - the fact that they access memory is almost incidental. I don't think it goes against the post you linked</p>



<a name="215531717"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215531717" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Diggsey <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215531717">(Nov 04 2020 at 01:21)</a>:</h4>
<p>in the same way that you can never get <code>undef</code> when reading from a file, it doesn't make sense to get undef from a volatile load</p>



<a name="215532411"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215532411" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215532411">(Nov 04 2020 at 01:34)</a>:</h4>
<p>if it's actually MMIO its more complex i think since you can still have data races on MMIO (cross process, although obviously same-process too) which is still UB when that happens i think</p>



<a name="215532462"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215532462" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215532462">(Nov 04 2020 at 01:34)</a>:</h4>
<p>hmmmm, or maybe that doesnt matter</p>



<a name="215552657"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215552657" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215552657">(Nov 04 2020 at 08:32)</a>:</h4>
<p><span class="user-mention silent" data-user-id="143274">Amanieu</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F/near/215531114">said</a>:</p>
<blockquote>
<p>In my view a volatile load/store is the same as an inline asm block with a load/store instruction.</p>
</blockquote>
<p>I think that is not compatible with LVLM's model of volatile and your model of asm. You said in the past it should be legal to replace one asm block by another (e.g. self-modifying code), i.e., the compiler may not make any assumptions based on the contents of the asm block. OTOH, LLVM will happily reorder volatile accesses wrt other non-volatile accesses, which I don't think your model for asm blocks permits.</p>



<a name="215552680"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215552680" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215552680">(Nov 04 2020 at 08:33)</a>:</h4>
<p>related issue for OOB loads: <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/2">https://github.com/rust-lang/unsafe-code-guidelines/issues/2</a></p>



<a name="215552912"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215552912" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215552912">(Nov 04 2020 at 08:35)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209168">Thom Chiovoloni</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F/near/215531390">said</a>:</p>
<blockquote>
<p>it goes against <a href="https://www.ralfj.de/blog/2019/07/14/uninit.html">https://www.ralfj.de/blog/2019/07/14/uninit.html</a> IIUC, although perhaps that could be adjusted for volatile if that's really not an issue.</p>
</blockquote>
<p>as in, letting volatile loads perform an implicit <code>freeze</code>? that could be done, but LLVM seems unwilling to do so: <a href="https://bugs.llvm.org/show_bug.cgi?id=42435">https://bugs.llvm.org/show_bug.cgi?id=42435</a></p>



<a name="215553172"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215553172" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215553172">(Nov 04 2020 at 08:38)</a>:</h4>
<p><span class="user-mention silent" data-user-id="143274">Amanieu</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F/near/215531211">said</a>:</p>
<blockquote>
<p>You can't const-propagate through volatile operations, so <code>undef</code> is never returned.</p>
</blockquote>
<p>that's the same LLVM bug -- it seems reasonable to assume that <code>undef</code> is never returned, and I'd be onboard with guaranteeing that for Rust (if the lang team <a href="https://bugs.llvm.org/show_bug.cgi?id=42435">is happy to ignore all the concerns this raises</a>), but we can only do that if our backends also guarantee the same (or if we are okay adjusting codegen to add explicit <code>freeze</code> after each volatile load, I guess)</p>



<a name="215632455"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215632455" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215632455">(Nov 04 2020 at 19:50)</a>:</h4>
<p>Probably normal past-the-end reads could be <code>undef</code>, but the <code>undef</code> part can be bypassed by reading as a newtype over <code>[u8; N]</code>, maybe with <code>repr(align(N))</code>.  (I have no idea about the correctness question of whether the whole read is UB, though.)</p>



<a name="215952280"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215952280" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215952280">(Nov 07 2020 at 12:11)</a>:</h4>
<blockquote>
<p>Probably normal past-the-end reads could be undef</p>
</blockquote>
<p>only if you convince LLVM to treat it that way^^</p>



<a name="215952331"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215952331" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215952331">(Nov 07 2020 at 12:12)</a>:</h4>
<p>AFAIK currently LLVM will do things like "oh you did an 8-byte read, this means the pointer cannot possibly alias that 4-byte object here"</p>



<a name="215961689"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961689" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961689">(Nov 07 2020 at 16:12)</a>:</h4>
<blockquote>
<p>as in, letting volatile loads perform an implicit freeze? that could be done, but LLVM seems unwilling to do so: <a href="https://bugs.llvm.org/show_bug.cgi?id=42435">https://bugs.llvm.org/show_bug.cgi?id=42435</a></p>
</blockquote>
<p>So, I guess the precise comment is: <a href="https://bugs.llvm.org/show_bug.cgi?id=42435#c9">https://bugs.llvm.org/show_bug.cgi?id=42435#c9</a>, which says:</p>
<blockquote>
<p>In terms of adding semantics to volatile, I think that's not a good approach. There's way too much history of under-defined rules and weird semantics associated with volatile operations. And I don't want to unintentionally constrain better solutions for handling "undefined" memory like padding, given we're still not completely sure what they look like.</p>
</blockquote>
<p>Honestly that's hard to argue with. Volatile has a ton of baggage from C. If it was the way to perform frozen reads, then, among other things, the compiler would be required to follow the other rules of volatile — mostly that every load and store that appears both happens and is in program order. That's actually pretty undesirable, honestly.</p>
<p>If there were a way to do frozen reads¹, depending on the kind of read I would <strong>want</strong> the compiler to do many² of the same optimizations that it would do on, say, <code>ptr::read</code>, assuming that it would be a valid transformation. That is, stuff like remove it if the result is unused, hoist it out of a loop, merge it with other loads, move the loaded value to a register (e.g. for small structs with padding bytes), remove it using store-load forwarding...</p>
<p>With volatile (let alone inline asm) I'd get none of those. This is still better than nothing, but I think the LLVM commentor is right to want to know what a better solution here looks like.</p>
<p>¹ probably with some reasonable limitations that are UB if violated (This being unsafe is fine, I think). For example:</p>
<ul>
<li>for OOB reads they can't read past the end of a page line³...</li>
<li>for uninit reads they're still UB if the page has been freed or has never been written to (or whatever is needed to precisely make the issues with pages from stuff like MADV_FREE irrelevant, besides actually writing to the memory which would really not be good IMO).</li>
</ul>
<p>² Presumably with a frozen read, some optimizations aren't valid, or are only conditionally valid, etc. Even of the ones I mention there I bet not all of those can work.</p>
<p>³ Honestly I wouldn't be surprised if, say, OOB reads is the odd one out and is too problematic to allow this way...  the more I think the dodgier it gets... I'd hope inline asm still works for them, though.</p>



<a name="215961842"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961842" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961842">(Nov 07 2020 at 16:16)</a>:</h4>
<p>With <code>freeze(read(x))</code>, I think uninit memory is already handled properly -- this does represent the fact that doing multiple reads can return different results even if nobody does a write in the mean time</p>



<a name="215961846"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961846" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961846">(Nov 07 2020 at 16:16)</a>:</h4>
<p>this will indeed block some optimizations, but way fewer than volatile</p>



<a name="215961859"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961859" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961859">(Nov 07 2020 at 16:17)</a>:</h4>
<p>but then we'd need a new surface-level API in Rust that expresses these kinds of reads -- maybe that is a good thing</p>



<a name="215961917"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961917" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961917">(Nov 07 2020 at 16:18)</a>:</h4>
<p>my concern with <code>freeze(read(x))</code> is: if the value read has only some bytes uninitialized, i thought the result was fully <code>uninit</code> in llvm's eyes, and <code>freeze</code> wouldn't "regain" those bytes of the value which were actually initialized</p>



<a name="215961922"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961922" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961922">(Nov 07 2020 at 16:18)</a>:</h4>
<p>(that LLVM bug was written before <code>freeze</code> existed... assuming that <code>freeze</code> can be applied to all types that one can no voaltile loads at, then indeed nowadays there is no need any more for volatile loads to make such promises, as the same can be expressed more orthogonally with a separate freeze instruction)</p>



<a name="215961927"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961927" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961927">(Nov 07 2020 at 16:19)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209168">Thom Chiovoloni</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F/near/215961917">said</a>:</p>
<blockquote>
<p>my concern with <code>freeze(read(x))</code> is: if the value read has only some bytes uninitialized, i thought the result was fully <code>uninit</code> in llvm's eyes, and <code>freeze</code> wouldn't "regain" those bytes of the value which were actually initialized</p>
</blockquote>
<p>that is a problem no matter which approach we use -- <code>iX</code> values in LLVM currently are all-or-nothing in terms of initialization</p>



<a name="215961985"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961985" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961985">(Nov 07 2020 at 16:20)</a>:</h4>
<p>one can use <code>[i8 x N]</code> or whatever the syntax is to obtain per-byte initialization</p>



<a name="215961989"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215961989" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215961989">(Nov 07 2020 at 16:20)</a>:</h4>
<p>a benefit of it not being a new read api is that <code>freeze(read_atomic(x, ord))</code>, <code>freeze(read_unaligned(x))</code>, <code>freeze(read_volatile(x))</code> all work.</p>



<a name="215962059"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215962059" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215962059">(Nov 07 2020 at 16:22)</a>:</h4>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span> can [i8 x N] be used to do, say, an atomic load?</p>



<a name="215962064"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215962064" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215962064">(Nov 07 2020 at 16:22)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209168">Thom Chiovoloni</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F/near/215962059">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="120791">RalfJ</span> can [i8 x N] be used to do, say, an atomic load?</p>
</blockquote>
<p>no idea</p>



<a name="215962081"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215962081" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215962081">(Nov 07 2020 at 16:23)</a>:</h4>
<p>i mean, even if it can rust doesn't expose anyway of using anything besides u64 to load a, well, u64 atomically</p>



<a name="215962224"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can%20inline%20asm%20read%20past%20the%20end%20of%20arrays/allocations/etc%3F/near/215962224" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Can.20inline.20asm.20read.20past.20the.20end.20of.20arrays.2Fallocations.2Fetc.3F.html#215962224">(Nov 07 2020 at 16:26)</a>:</h4>
<p>maybe that's just a libcore design problem though.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>